package com.ujson.uaa.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ujson.base.common.dto.Res;
import com.ujson.base.common.enums.ErrorCode;
import com.ujson.base.common.utils.LogUtil;
import com.ujson.uaa.types.User;
import com.ujson.uaa.utils.JwtUtils;
import com.ujson.uaa.utils.ResponseUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.RequestBody;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.Collections;
import java.util.Objects;

/**
 * <h3>ujson-parent</h3>
 * <p>jwt登录过滤器</p>
 *
 * @author JerryLiu  a1031757312@gmail.com
 * @version 1.0
 * @date 2021-11-20 13:13
 */
@Slf4j
public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {
    public static final String USERNAME = "username";
    public static final String PASSWORD = "password";
    private String loginUrl;
    private JwtUtils jwtUtils;
    private AuthenticationManager authenticationManager;

    public TokenLoginFilter(String loginUrl, JwtUtils jwtUtils, AuthenticationManager authenticationManager) {
        this.loginUrl = loginUrl;
        this.jwtUtils = jwtUtils;
        // super(new AntPathRequestMatcher("/login", "POST")); // 设置拦截/login POST进行处理
        this.authenticationManager = authenticationManager;
    }

    @Override
    public Authentication attemptAuthentication(
            HttpServletRequest request,
            HttpServletResponse response) throws AuthenticationException {
        String username = null,
                password = null;

        username = request.getParameter(USERNAME);
        password = request.getParameter(PASSWORD);

        if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
            try {
                //从json中获取username和password
                String body = StreamUtils.copyToString(request.getInputStream(), Charset.forName("UTF-8"));

                if(StringUtils.isNotBlank(body)) {
                    JSONObject jsonObj = JSON.parseObject(body);
                    username = jsonObj.getString("username");
                    password = jsonObj.getString("password");
                }
            } catch (Exception ex) {
                LogUtil.error(log, "read username or password paramater from post error.", ex);
            }

            if (Objects.isNull(username))
                username = "";
            if (Objects.isNull(password))
                password = "";
            username = username.trim();
        }

        return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password, Collections.EMPTY_LIST));
    }

    /** 认证失败回调 */
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        LogUtil.error(log, "un success authentication.");
        // 返回认证失败信息
        ResponseUtil.out(response, Res.fail(ErrorCode.AUTH_FAIL));
    }

    /** 认证成功回调 */
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        LogUtil.info(log, "success authentication.");
        // super.successfulAuthentication(request, response, chain, authResult);
        /*Collection<? extends GrantedAuthority> authorities = authResult.getAuthorities();
        StringBuffer as = new StringBuffer();
        for (GrantedAuthority authority : authorities) {
            as.append(authority.getAuthority())
                    .append(",");
        }*/
        ResponseUtil.out(response, Res.success(jwtUtils.createToken(authResult.getName())));
    }

}
